home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / programm.ing / progem.lzh / wind16.prf < prev    next >
Encoding:
Text File  |  1987-06-23  |  16.1 KB  |  323 lines

  1. .!****************************************************************************
  2. .! 
  3. .! ANTIC PUBLISHING INC., COPYRIGHT 1985.  REPRINTED BY PERMISSION.
  4. .!
  5. .! ** Professional GEM ** by Tim Oren
  6. .!
  7. .! Proff File by ST enthusiasts at
  8. .! Case Western Reserve University
  9. .! Cleveland, Ohio
  10. .! uucp : decvax!cwruecmp!bammi
  11. .! csnet: bammi@case
  12. .! arpa : bammi%case@csnet-relay
  13. .! compuserve: 71515,155
  14. .!
  15. .!****************************************************************************
  16. .!
  17. .!
  18. .!****************************************************************************
  19. .!
  20. .!            Begin Part 16
  21. .!
  22. .!****************************************************************************
  23. .!
  24. .PART XVI Interface Potpourri #1
  25. .PP
  26. This issue of ST PRO GEM,  number 16 in the series,  presents
  27. code  implementing  several user  interface  techniques:  progress
  28. indicators, rubber boxes, and draggable boxes with mouse sensitive
  29. targets.   The  code  also  includes  some  utility  routines  for
  30. handling resources, event calls, and VDI line drawing.
  31. .PP
  32. The  downloads  for this column are available on DL3  of  the
  33. ATARI16 SIG: PCS-58.  Note the plural - in addition to the usual C
  34. sources  stored  in GMCL16.C,  the files  GMCL16.RSC,  GMCL16.DFN,
  35. GMCL16.H,  and  GMCL16.RSH  are a template resource  for  building
  36. progress boxes.   GMCL16.RSC is the resource binary,  and GMCL16.H
  37. is  its  symbol binding file,  to be used with GMCL16.C.   The RSH
  38. file  is  a C image of the resource - you would need  STCREATE  to
  39. regenerate it.
  40. .PP
  41. GMCL16.DFN is the binary symbol file for the resource.  It is
  42. in  the format used by the NEW ST Resource Construction  Set.   If
  43. you are a developer, you should download this new version from DL7
  44. of PCS-57.   It fixes a number of bugs, and has a much faster user
  45. interface.
  46. .SH MAKING PROGRESS.
  47. The need for feedback in interface designs
  48. has  been  discussed in previous columns.   One instance which  is
  49. often  necessary is the so-called progress indicator.   A progress
  50. indicator is used when your application is doing a long operation.
  51. It  shows that the function is continuing satisfactorily,  and  is
  52. not hung in a loop.  When possible, it also gives an indication of
  53. the  fraction  of  the operation which has  been  completed.   The
  54. thermometer  bars  on the Desktop format and copy  operations  are
  55. examples.
  56. .PP
  57. The sample code shows two types of progress indicator.   Both
  58. are  built within the structure of a dialog resource.   The  first
  59. type  uses  a variable line of text to describe each phase  of  an
  60. operation as it occurs.  The rewriting of the text provides action
  61. on  the  screen;  the  fact that it is different each  time  gives
  62. reassurance  that  the program is not hung.   The second  type  of
  63. indicator  is the thermometer bar.   This is more useful when  the
  64. operation  is  uniform,  allowing  you to  estimate  the  fraction
  65. completed.  Let's look at the code.
  66. .PP
  67. The routines beg_prog() and end_prog() are common to the  two
  68. types.   The  code is very similar to the standard dialog handling
  69. procedure,  but is broken into two parts.  Beg_prog() assumes that
  70. the  progress  indicator  box is defined by a  dialog  tree  named
  71. PROGRESS.   Such  a  tree is provided in  GMCL16.RSC.   Beg_prog()
  72. makes  the usual calls to center and draw the box.   The rectangle
  73. computed in the centering operation is stored via a GRECT  pointer
  74. passed  in  the  parameter.   This rectangle compensates  for  the
  75. outline  around the box,  and must be supplied to end_prog()  when
  76. the operation is complete.
  77. .PP
  78. The  first version of set_prog() in the  download  implements
  79. the changing text progress indicator.  It looks in a tree labelled
  80. STRINGS for the object number which is passed as a parameter.   It
  81. is assumed that this object is a G_STRING.  The address of the new
  82. text  is loaded from the object's ob_spec field.   (For those with
  83. the  new RCS,  it would be easy to alter this routine to use  free
  84. strings.  Simply replace the first two lines with:
  85. .sp
  86. .ce
  87. rsrc_gaddr(R_STRING, strno, &saddr);
  88. .sp
  89. and  supply parameters which are the names of strings in  a  FRSTR
  90. box.)
  91. .PP
  92. Once the new text is found,  the set_text() utility is called
  93. to  update  the TEDINFO attached to object PLINE in  the  PROGRESS
  94. tree.   Set_text()  will insert the new text address in  te_ptext,
  95. and the new text length in te_txtlen.   Disp_obj() is then used to
  96. redraw only the rectangle belonging to PLINE.
  97. .PP
  98. PLINE  must  be defined as a G_BOXTEXT object  with  a  solid
  99. white  background,  and with the CENTERED attribute set.   It must
  100. extend entirely across the progress box.  This guarantees that the
  101. previous  text  will  be covered over,  and the new text  will  be
  102. centered in the box.
  103. .PP
  104. The  second version of set_prog() implements the  thermometer
  105. bar progress indicator.  The PROGRESS tree also includes an object
  106. PROBOX  which  defines the outline of the thermometer.   It  is  a
  107. G_BOX  object  with a solid white background,  and  a  one-outside
  108. border.   The  object  PROBAR is nested inside it,  with the  left
  109. edges  matching.   PROBAR  is  also  a G_BOX,  with  a  solid  red
  110. background  and a one-outside border as well.   Set_prog() creates
  111. the thermometer effect by growing and redrawing PROBAR.
  112. .PP
  113. Set_prog()  requires two parameters.   Maxc is an estimate of
  114. the total duration of the operation, in arbitrary units.  Value is
  115. the (new) amount completed,  in the same units.  Set_prog performs
  116. two operations.   First,  it computes the fraction value/maxc, and
  117. sets PROBAR to that fraction of the width of PROBOX.   Second,  it
  118. computes the rectangle which is the difference between the old and
  119. new  widths of PROBAR,  and redraws only that part of the progress
  120. box.   This  prevents  an  annoying flash on the screen  when  the
  121. indicator is updated.
  122. .PP
  123. These two types of progress indicators have been presented in
  124. separate routines for convenience in explanation.   You can easily
  125. combine  them  in a single procedure to create an  indicator  with
  126. both effects.
  127. .PP
  128. The  final progress indicator routine is  called  esc_prog().
  129. During  many lengthy operations is desirable to provide  an  abort
  130. option  to the user.   Esc_prog() lets you do this by polling  the
  131. keyboard  for  an escape (ESC) character.   A zero timer value  is
  132. used  to guarantee an immediate return if no character  is  found.
  133. Characters other than escape are ignored.
  134. .PP
  135. Esc_prog()  returns TRUE if an abort is requested,  and FALSE
  136. if  the  operation is to continue.   In your application,  you can
  137. either  pair  calls  to  set_prog()  and  esc_prog(),   or  recode
  138. set_prog()  to automatically make the abort check.   In any  case,
  139. you  should add an information line to the progress  box,  telling
  140. the user how the operation may be halted.
  141. .PP
  142. Of  course,  this type of progress indicator is not the  only
  143. option  available on the ST.   Other ideas such as changing window
  144. titles,  or displaying a succession of differing icons are equally
  145. valid.   Sometimes  the nature of your application may suggest  an
  146. alternate metaphor.  For instance, the progress of recalculating a
  147. spreadsheet might be indicated by darkening successive columns  in
  148. a  miniature  image  of the sheet.   Occasionally,  the  computing
  149. operation  is  visual  itself,  and will not require  an  explicit
  150. indicator.   An  example  is  redisplaying  objects  in  a  2D  or
  151. 3D drawing program.
  152. .SH BOXED  IN.
  153. The  second part of the download implements  two
  154. types  of user interaction using the mouse.   The first creates  a
  155. "rubber  box"  on  the  screen,  that  is,  a box  whose  size  is
  156. controlled  by  moving  the mouse.   This is similar  to  the  AES
  157. graf_rubberbox  call,  but allows the box to move in any direction
  158. from  its origin,  while the GEM function only allows movement  to
  159. the lower right.
  160. .PP
  161. The second technique allows the user to drag the outline of a
  162. box around the screen using the mouse.   Again, this is similar to
  163. the AES graf_dragbox call, but this version is augmented with code
  164. which "hotspots" selectable objects when the mouse and object pass
  165. over  them.   These routines are another illustration of the usage
  166. of  the evnt_multi function,  and its combination with VDI drawing
  167. to create new interaction techniques.
  168. .PP
  169. The  "rubber  box" subroutine is called  fourway_box().   Its
  170. parameters are the current VDI handle (NOT a window handle!),  and
  171. two  GRECT  pointers.   The first GRECT must have its g_x and  g_y
  172. initialized  with the fixed point of the rubber box.   The  second
  173. GRECT contains an outer bound box for the stretching action.
  174. .PP
  175. Fourway_box()  begins  by setting the VDI  drawing  mode  and
  176. color.   The  exclusive  or,  black  combination  guarantees  that
  177. redrawing  a figure twice in the same location will exactly  erase
  178. it.  Next, the routine asserts the mouse control flag.  This stops
  179. the  window manager from tracking the mouse,  with the effect that
  180. menus will not drop down during the operation.
  181. .PP
  182. The  fixed coordinates are saved in the variables ox and  oy,
  183. and  an initial mouse reading is obtained with  graf_mkstate.   At
  184. this point, the event loop is entered.
  185. .PP
  186. At each iteration,  the loop finds the upper left most of the
  187. fixed  vertex  and  the current mouse position,  and  updates  the
  188. tracking GRECT accordingly.   A call to the utility rc_intersect()
  189. is  used  to  restrict the size of the rubber  box  to  the  given
  190. limiting  rectangle.   Note that if you need a lower limit to  the
  191. size of the rubber box, it can be achieved by adding another GRECT
  192. pointer "lower" to the parameter list, and using the call
  193. .sp
  194. .ce
  195. rc_union(lower, rubber);
  196. .sp
  197. This  works because the union operation selects the larger of  two
  198. rectangles if they are nested.
  199. .PP
  200. Rub_wait()  will be described in detail below.   Its  returns
  201. are the new mouse position, and an indication of the current mouse
  202. button  state.   If  the button remains down,  the loop continues.
  203. When the button is released,  the rubber box terminates,  since it
  204. is   a   "spring-loaded"   modal   operation.     Before   ending,
  205. fourway_box()  returns mouse control to the window  manager.   The
  206. return  from the routine is found in the rubber GRECT,  and is the
  207. final extent of the box.
  208. .PP
  209. Rub_wait()  is  a utility used by both box  techniques.   Its
  210. purpose  is  to do one step of the box animation,  and wait for  a
  211. mouse  movement,   or  the  release  of  the  button.   Rub_wait()
  212. preserves the state of the screen.
  213. .PP
  214. The  first action is to draw an exclusive or'ed  dotted  line
  215. box at the given rectangle.   Next, rub_wait() calls evnt_multi to
  216. wait for the mouse button to come up,  or the mouse to move out of
  217. a one pixel rectangle.   When the event is detected, the same code
  218. is  used  to remove the box.   A value of TRUE is returned if  the
  219. mouse  button is still down;  the curious logical construction  is
  220. necessary since BOTH events could occur at once.
  221. .PP
  222. A  short examination of the vdi_xbox() code is  also  useful.
  223. After converting the rectangle to polyline format, the vdi_xline()
  224. routine  is called.   Vdi_xline draws a dotted line,  but does not
  225. use the VDI line style attribute.  This is avoided because the VDI
  226. has  problems with corner points when drawing styled lines in  XOR
  227. mode.   Instead,  a  selection  is made from a set of user defined
  228. line  styles,  based  on  the  direction of the  stroke,  and  the
  229. odd/evenness of the starting horizontal pixel.   This assures that
  230. the figure will be exactly erasable.
  231. .SH HOT STUFF?
  232. The drag box routine is more subtle, because care
  233. is  needed  to  correctly synchronize the movement  of  the  mouse
  234. cursor and the box,  and the highlighting of target objects.   The
  235. parameters  vdi_handle  and  limit  are  identical  to  those   in
  236. fourway_box().  The GRECT pointed to by box contains the width and
  237. height of the movable box when hot_dragbox() is entered.   On exit
  238. it  also  contains  the  last x,y coordinates  of  the  box.   The
  239. variable tree is a pointer to the root of a resource tree defining
  240. the  hot  spots  for  the drag  operation.   Only  objects  tagged
  241. SELECTABLE  are hotspotted.   Hot_dragbox() returns the number  of
  242. such  an object if the box is "dropped" on it,  otherwise a NIL is
  243. returned.
  244. .PP
  245. Initialization  proceeds  as above,  until  the  graf_mkstate
  246. call.   Here  is the first potential synchronization problem.   If
  247. the  user moves the mouse very quickly after initiating the  drag,
  248. it may already be outside the box by the time graf_mkstate samples
  249. the position.   The min/max operations given lock the box onto the
  250. cursor, no matter where it has strayed.  The mouse/box offsets, ox
  251. and oy, will remain constant for the rest of the operation.
  252. .PP
  253. Hover_obj  will  contain the number of the  object  which  is
  254. currently  highlighted.   It is initialized to NIL,  indicating no
  255. object is currently marked.   Hot_dragbox() now enters a loop with
  256. termination conditions identical to the rubber box.
  257. .PP
  258. The  current  desired  position of the  box  is  computed  by
  259. subtracting the box/mouse offset from the current mouse  position.
  260. The  rc_constrain() call ensures that the box will not  leave  the
  261. bounding rectangle.   Note that rc_intersect would not work here -
  262. it  would  alter  the  size of  the  draggable  box,  rather  than
  263. "nudging" it back into the bounds.
  264. .PP
  265. Upon  return from rub_wait(),  a number of conditions must be
  266. checked  to  determine the correct object to  highlight,  if  any.
  267. First,  we  must  make sure that the mouse is actually within  the
  268. legal bounds.   If not,  there may be an ambiguous selection, with
  269. the mouse over one object and the box over another.   We choose to
  270. do nothing in this case,  and set hover_obj to NIL.   If the mouse
  271. is in bounds, objc_find looks for a target object.  If one exists,
  272. it must be SELECTABLE, or it is forced to NIL.
  273. .PP
  274.  Next  the new object,  stored in ret_obj,  is compared to the
  275. old highlighted object,  in hover_obj.   If they are different,  a
  276. switch  must  be  made.   Since either could be NIL,  a  check  is
  277. necessary before calling obj_toggle to invert/reinvert the  screen
  278. image  of  the  object.   When  the loop is  complete,  the  final
  279. hover_obj  is  returned  to  normal state  before  its  number  is
  280. returned.
  281. .PP
  282. You  may notice that this method of highlighting  objects  is
  283. different from the incremental tree descent and rectangles  method
  284. presented  in  column 13.   While not as efficient,  the objc_find
  285. technique  is simpler to code and may be adequate for  many  uses.
  286. If  your program will make heavy use of the drag box  routine,  or
  287. will  have  large  trees  of  target  objects,  you  may  wish  to
  288. integrate    the    incremental   hotspotting    algorithm    with
  289. hot_dragbox().   This would be simple to do; just use evnt_multi's
  290. second  mouse  rectangle for the states associated with  the  hot-
  291. spotter.   The  single  pixel rectangles would have to remain,  in
  292. order to maintain the animation effects.
  293. .SH A FEW  CHANGES.
  294. The  observant may have noticed  that  the
  295. promised  code for popup menus did not make it into  this  column.
  296. Instead,  it  will  appear in column 18 along with more  "graphics
  297. potpourri"  and  feedback replies.   The intervening  installment,
  298. number  17,  will  present  and  document the source  code  for  a
  299. complete   IBM/Atari GEM Resource conversion program.   This  will
  300. appear  concurrently with Mark Skapinker's article on  IBM/ST  GEM
  301. conversions  in  the second issue of START.   While  this  program
  302. will be of direct use to only a minority of ST developers, it will
  303. contain  utility code useful to all,  as well as demonstrations of
  304. dialog handling and the internal structure of resources.
  305. .PP
  306. Finally,  you  may also notice that the so-called portability
  307. macros have disappeared from the download.   Indeed, they are gone
  308. for good.   Since the beginning of this column,  the growth of the
  309. ST GEM developer community has outstripped that on the PC.   It no
  310. longer  seems  appropriate  to  inconvenience  ST  developers  and
  311. violate  standard C syntax for the sake of Intel's  design  flaws.
  312. Those  who still need compatibility with the PC may achieve it  by
  313. compiling under Intel large model,  or by writing "sed" scripts to
  314. translate   (tree+obj)->ob_spec  and  the  like  to  their   macro
  315. equivalents.
  316. .!
  317. .!
  318. .!*****************************************************************************
  319. .!*                                          *
  320. .!*                End Part 16                      *
  321. .!*                                          *
  322. .!*****************************************************************************
  323.